package org.batatasframework.support.database.metadatas;

import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.util.HashMap;
import java.util.Map;

import org.batatasframework.support.database.TableInfo;
import org.batatasframework.support.database.jdbc.ConnectionAccessor;
import org.springframework.util.Assert;

/**
 * <pre>
 * 用于管理数据库表的结构、定义等数据，与hibernate的处理过程可能重复；
 * 但本框架未必使用hibernate的定义，所以可以自定义子类来实现不同框架相同部分的共用问题
 * </pre>
 * 
 * <pre>
 * 本框架里，会把属性表也当成一个普通的大表来看待，至于如何生成属性表的临时表或直接返回查询结果的。
 * 可以由框架自动去完成；
 * 这里是对单独表的定义，如果定义了几个表关联起来的情况，那应该按视图的类型来处理；
 * 视图也是来自多个表的定义
 * </pre>
 * 
 * <hr/>
 * 
 * <pre>
 * Closure 
 * Formula
 * Fragment
 * Marker
 * Association 关联
 * Wrapper 包装
 * wrap  封装
 * Extractor 提取器
 * coordinator
 * factor 因子
 * </pre>
 * @author jackson
 *
 */
public class DatabaseMetadataResource {
//
//	/**
//	 * 注册或重新注册一个数据库表的元数据
//	 */
//	void registTableMetadata(String name, TableMetadata tableMetadata);
//	
//	/**
//	 * 用于加载数据库表的元数据信息
//	 */
//	TableMetadata loadTableMetadata(ConnectionAccessor connectionAccessor, TableInfo tableInfo) throws Exception;
//	
//	TableMetadata getTableMetadata(String name);
	
	private final static DatabaseMetadataResource resource = new DatabaseMetadataResource();
	
	private DatabaseMetadataResource(){}
	
	public static DatabaseMetadataResource getResource(){
		return resource;
	}
	
	/**
	 * 所有的对象都共用
	 */
	protected final Map<String, TableMetadata> tables = new HashMap<>();

//	@Override
	public void registTableMetadata(String name, TableMetadata tableMetadata) {
		tables.put(name, tableMetadata);
	}
	
//	@Override
	public TableMetadata getTableMetadata(String name) {
		return tables.get(name);
	}
	
	/**
	 * 根据表的定义，读取表的元数据的定义
	 */
//	@Override
	public TableMetadata loadTableMetadata(ConnectionAccessor connectionAccessor, TableInfo tableInfo) throws Exception{

		String identifier = tableInfo.getTableName();
		
		TableMetadata tableMetadata = tables.get(identifier);
		if(null != tableMetadata){
			return tableMetadata;
		}
		
		DatabaseMetaData meta = connectionAccessor.getMetaData();
//		ResultSet rs = meta.getTables(
//				tableInfo.getCatalogName(), 
//				tableInfo.getSchemaName(), 
//				tableInfo.getSourceName(), 
//				new String[] { "TABLE", "VIEW" });
		DatabaseTableStructure databaseTableStructure = null;
		try(ResultSet rs = meta.getTables(
				tableInfo.getCatalogName(), 
				tableInfo.getSchemaName(), 
				tableInfo.getSourceName(), 
				new String[] { "TABLE", "VIEW" })){
			String table = tableInfo.getSourceName();
			while ( rs.next() ) {
				String tableName = rs.getString("TABLE_NAME");
				if ( table.equalsIgnoreCase(tableName) ) {
					databaseTableStructure = new DatabaseTableStructure(rs);
					break;
				}
			}
//		}finally{
//			rs.close();
		}
		
		Assert.notNull(databaseTableStructure, "找不到数据库表：" + identifier);
		
		databaseTableStructure.initColumns(meta);
		tables.put(identifier, databaseTableStructure);
		return databaseTableStructure;
	}
}
